package com.yourcompany.handle;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandler.Sharable;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.DefaultChannelPromise;

import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.Iterator;
import java.util.Map.Entry;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;

import org.apache.log4j.Logger;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.yourcompany.PollServer;
import com.yourcompany.vo.UploadDataVo;

/**
 * 接受信息并且保存数据库
 * 
 * @author tzj 2016-10-12 下午2:16:12
 */
@Sharable
public class RevicMessageHandle extends ChannelInboundHandlerAdapter {

	Logger logger = Logger.getLogger("server");


	@Autowired
	JdbcTemplate jdbcTemplate;
	
	ExecutorService dboptGroup;

	BlockingQueue<Channel> channels;

	ScheduledExecutorService executorService = Executors.newScheduledThreadPool(10);
	
	@Autowired
	AdminHandle adminHandle;
	
	
	/**
	 * 请求的报文格式
	 */
	int[][] requestrulesdata={
			{10,0X000A},//客户端–>服务器流量计数据上传确认
			{4,0X8884},//采集器—>服务器心跳包格式：
			{10,0X7776}//采集器—>服务器回应服务器发送命令格式
			
	};
	
	/**
	 * 响应的报文格式
	 */
	int[][] reponserulesdata={
			{10,0X800A},//服务器–>客户端流量计数据上传确认
			{4,0X6771},//服务器—>采集器回应心跳包格式：
			{10,0X7776},//服务器—>采集器发送命令格式：
			{10,0X737A}//服务器–>客户端修改流量计数据
			
	};

	public RevicMessageHandle(){
		
	}
	public RevicMessageHandle(PollServer pollServer) {
		
		this.channels=pollServer.getChannels();
		this.adminHandle=pollServer.getAdminHandle();
		this.dboptGroup=pollServer.getDboptGroup();
		System.out.println("init");
	}

	@Override
	public void channelActive(ChannelHandlerContext ctx) throws Exception {
		logger.debug(ctx.channel().remoteAddress() + "连接"
				+ Thread.currentThread());
		channels.add(ctx.channel());

	}

	@Override
	public void channelInactive(ChannelHandlerContext ctx) throws Exception {
		closeChannel(ctx);
	}

	@Override
	public void channelRead(ChannelHandlerContext ctx, Object msg)
			throws Exception {
		// 读取数据

		ByteBuf buf = (ByteBuf) msg;
		int  readhead=buf.readInt();
		printBuf2String("请求",buf);
		
		if(readhead==0X55AA0100){

			int i=0;
			for (i=0; i < requestrulesdata.length; i++) {
					 int mask=buf.getUnsignedShort(requestrulesdata[i][0]);
					 if(requestrulesdata[i][1]==mask) break;
			         
			}
			switch (i) {
				case 0:
					uploadData(ctx, buf);
					break;
				case 1:
					ping(ctx, buf);
					break;
				case 2:
					break;
			}
			
		}else{
			ctx.fireChannelRead(msg);
		}
	

	}

	/**
	 * 把一个buf打印成字符串
	 * tzj 2016-11-24 下午2:39:13
	 */
	void  printBuf2String(String target,ByteBuf buf ){
		buf.resetReaderIndex();
		StringBuilder builder = new StringBuilder();
		while (buf.readableBytes() > 0) {

			String str=Integer.toHexString(buf.readUnsignedByte());
			if(str.length()==1)
				str="0"+str;
			builder.append(str);
		}
		logger.debug(target+"转化成字符串后：" + builder.toString());
		buf.resetReaderIndex();
	}
	
/**
 * 处理心跳
 * @param ctx
 * @param buf
 */
	void   ping(ChannelHandlerContext ctx,final ByteBuf buf){
		
		buf.resetReaderIndex();
		buf.setShort(4, reponserulesdata[1][1]);
		printBuf2String("心跳回复",buf);
		ctx.writeAndFlush(buf,new DefaultChannelPromise(ctx.channel()){
			@Override
			public boolean trySuccess() {
                   logger.debug("发送"+this.channel()+"成功");
				return super.trySuccess();
			}
		});
	}
	
	/**
	 * 处理数据上传
	 * tzj 2016-11-24 下午4:27:09
	 */
	void   uploadData(ChannelHandlerContext ctx,ByteBuf buf){
		
		buf.resetReaderIndex();
		saveIt(buf);
		buf.resetReaderIndex();
		

	   adminHandle.pushMsg2AdminBuf(ctx.alloc(), buf);
		
		
		
	}
	
	public   int  saveIt(final ByteBuf byteBuf){
		
		String json=null;
		try {
			json= JSON.toJSONString(
					createUpContentFromBuf(byteBuf));
			
			logger.debug("转化成json"+json);
		} catch (Exception e) {
			 logger.debug("错误",e);
		}
		
		
		if(json!=null){
			
			JSONObject jsonObject=JSON.parseObject(json);
			StringBuilder builder=new StringBuilder("INSERT  INTO toe_device");
			StringBuilder fieldsBuilder=new StringBuilder("(");
			StringBuilder valuesBuilder=new StringBuilder(" values (");
			 Iterator<Entry<String, Object>> iterator=jsonObject.entrySet().iterator();
			 while(iterator.hasNext()){
				 Entry<String, Object> entry=iterator.next();
				 fieldsBuilder.append( entry.getKey()+",");
				 valuesBuilder.append("'"+entry.getValue()+"',");
			 }
			 fieldsBuilder.append(")");
			 valuesBuilder.append(")");
			 String sql=builder.append(fieldsBuilder).append(valuesBuilder).toString().replaceAll(",\\)", ")");
			 return jdbcTemplate.update(sql);
			
		}
		return 0;
	}
	
	public	UploadDataVo  createUpContentFromBuf(ByteBuf buffer) throws Exception{
		
		buffer.resetReaderIndex();
		buffer.readerIndex(
				buffer.readerIndex()+4
				);
		Field[] fields=UploadDataVo.class.getDeclaredFields();
	
		UploadDataVo uploadDataVo=new UploadDataVo();
		
		for (int i = 0; i < fields.length; i++) {
			Field field=fields[i];
			Object value=null;
			
			if(Modifier.isStatic(field.getModifiers()))
				continue;
			
			if(field.getType()==byte.class){
				value=buffer.readByte();
				
			}else if(field.getType()==int.class){
				value=buffer.readInt();
			}else if(field.getType()==short.class){
				value=buffer.readShort();
			}else if(field.getName().equals("vendornumbe")){
				int len=uploadDataVo.getVendornumbe().length;
				byte[] bs=new byte[len];
				buffer.readBytes(bs);
				value=bs;
			}else if(field.getName().equals("collectiontime")){
				int len=uploadDataVo.getVendornumbe().length;
				byte[] bs=new byte[len];
				buffer.readBytes(bs);
				value=bs;
			}

			
			try {

				BeanUtils.getWriteMethodParameter(
						new PropertyDescriptor(field.getName(), 
								UploadDataVo.class)).getMethod().invoke(uploadDataVo,  value);
			} catch (Exception e) {
					e.printStackTrace();
			}
		}
		
		return uploadDataVo;
	}
	
	/**
	 * 关闭通道
	 * tzj 2016-11-24 下午2:31:48
	 */
	void closeChannel(ChannelHandlerContext ctx){
		
		logger.debug(ctx.channel().remoteAddress() + "断开");
		channels.remove(ctx.channel());
	}
	
	@Override
	public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause)
			throws Exception {
		super.exceptionCaught(ctx, cause);
	}

	public static void main(String[] args) {
		
		ByteBuf byteBuf = ByteBufAllocator.DEFAULT.buffer();
		byteBuf.writeInt(0X55AA0100);
		byteBuf.writeShort(0x018b);
		byteBuf.writeShort(0x3e81);
		byteBuf.writeShort(0x0035);
		byteBuf.writeShort(0x000a);
		byteBuf.writeBytes(new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00 });
		byteBuf.writeInt(0x00000001);
		byteBuf.writeBytes(new byte[] { 0x00, 0x00, 0x00 });
		byteBuf.writeByte(0x00);

		byteBuf.writeBytes(new byte[] { 
				0x00, 0x04, 0x00, 0x2e, 0x00, 0x70,
				0x00, 0x00, 0x00, 0x00, 0x70, 0x07, 0x60, 0x0b, 0x00, 0x70,
				0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x50, 0x04,
				0x01, 0x00, 0x70, 0x08, 0x06, 0x00, 0x70, 0x00, 0x00, 0x00,
				0x70, 0x00, 0x00, 0x00, 0x72, 0x0a, 0x00, 0x00, 0x00, 0x00,
				0x00, 0x00, 0x00, 0x00, 0x04, 0x0e, 0x05

		});
		byteBuf.writeInt(0xaa55);
		
		
		RevicMessageHandle handle=new RevicMessageHandle();
		try {
			System.out.println(
					handle.createUpContentFromBuf(byteBuf));
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		
		
		
	}

}
